package com.videoweb.model;

import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.*;

@Data
@TableName("upload_status")
public class UploadStatus {
    
    @TableId(type = IdType.AUTO)
    private Long id;
    
    @TableField("file_hash")
    private String fileHash;
    
    @TableField("original_filename")
    private String originalFilename;
    
    @TableField("file_size")
    private Long fileSize;
    
    @TableField("total_chunks")
    private Integer totalChunks;
    
    @TableField("uploaded_chunks")
    private String uploadedChunks; // JSON格式存储已上传分片索引
    
    @TableField("chunk_size")
    private Integer chunkSize = 2 * 1024 * 1024; // 默认2MB
    
    @TableField("status")
    private UploadStatusEnum status = UploadStatusEnum.UPLOADING;
    
    @TableField("upload_dir")
    private String uploadDir;
    
    @TableField("final_path")
    private String finalPath;
    
    @TableField("user_id")
    private Long userId;
    
    @TableField("title")
    private String title;
    
    @TableField("description")
    private String description;
    
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createdAt;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updatedAt;
    
    // 上传状态枚举
    public enum UploadStatusEnum {
        UPLOADING("uploading", "上传中"),
        COMPLETED("completed", "已完成"),
        FAILED("failed", "失败"),
        MERGING("merging", "合并中");
        
        @com.baomidou.mybatisplus.annotation.EnumValue
        private final String code;
        private final String desc;
        
        UploadStatusEnum(String code, String desc) {
            this.code = code;
            this.desc = desc;
        }
        
        public String getCode() {
            return code;
        }
        
        public String getDesc() {
            return desc;
        }
    }
    
    // 工具方法：获取已上传分片集合
    public Set<Integer> getUploadedChunkSet() {
        if (uploadedChunks == null || uploadedChunks.trim().isEmpty()) {
            return new HashSet<>();
        }
        
        try {
            ObjectMapper mapper = new ObjectMapper();
            List<Integer> chunks = mapper.readValue(uploadedChunks, 
                new TypeReference<List<Integer>>() {});
            return new HashSet<>(chunks);
        } catch (JsonProcessingException e) {
            return new HashSet<>();
        }
    }
    
    // 工具方法：设置已上传分片集合
    public void setUploadedChunkSet(Set<Integer> chunks) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            List<Integer> sortedChunks = new ArrayList<>(chunks);
            Collections.sort(sortedChunks);
            this.uploadedChunks = mapper.writeValueAsString(sortedChunks);
        } catch (JsonProcessingException e) {
            this.uploadedChunks = "[]";
        }
    }
    
    // 添加已上传分片
    public void addUploadedChunk(Integer chunkIndex) {
        Set<Integer> chunks = getUploadedChunkSet();
        chunks.add(chunkIndex);
        setUploadedChunkSet(chunks);
    }
    
    // 检查是否所有分片都已上传
    public boolean isAllChunksUploaded() {
        return getUploadedChunkSet().size() == totalChunks;
    }
    
    // 获取上传进度百分比
    public double getProgressPercentage() {
        if (totalChunks == null || totalChunks == 0) {
            return 0.0;
        }
        return (double) getUploadedChunkSet().size() / totalChunks * 100;
    }
    
    // 获取缺失的分片索引列表
    public List<Integer> getMissingChunkIndexes() {
        Set<Integer> uploadedSet = getUploadedChunkSet();
        List<Integer> missing = new ArrayList<>();
        
        for (int i = 0; i < totalChunks; i++) {
            if (!uploadedSet.contains(i)) {
                missing.add(i);
            }
        }
        
        return missing;
    }
    
    // 手动添加getter方法以确保兼容性
    public String getTitle() {
        return title;
    }
    
    public String getDescription() {
        return description;
    }
    
    public String getFinalPath() {
        return finalPath;
    }
    
    public Long getFileSize() {
        return fileSize;
    }
    
    // 添加更多必要的getter和setter方法
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getFileHash() {
        return fileHash;
    }
    
    public void setFileHash(String fileHash) {
        this.fileHash = fileHash;
    }
    
    public String getOriginalFilename() {
        return originalFilename;
    }
    
    public void setOriginalFilename(String originalFilename) {
        this.originalFilename = originalFilename;
    }
    
    public void setFileSize(Long fileSize) {
        this.fileSize = fileSize;
    }
    
    public Integer getTotalChunks() {
        return totalChunks;
    }
    
    public void setTotalChunks(Integer totalChunks) {
        this.totalChunks = totalChunks;
    }
    
    public String getUploadedChunks() {
        return uploadedChunks;
    }
    
    public void setUploadedChunks(String uploadedChunks) {
        this.uploadedChunks = uploadedChunks;
    }
    
    public Integer getChunkSize() {
        return chunkSize;
    }
    
    public void setChunkSize(Integer chunkSize) {
        this.chunkSize = chunkSize;
    }
    
    public UploadStatusEnum getStatus() {
        return status;
    }
    
    public void setStatus(UploadStatusEnum status) {
        this.status = status;
    }
    
    public String getUploadDir() {
        return uploadDir;
    }
    
    public void setUploadDir(String uploadDir) {
        this.uploadDir = uploadDir;
    }
    
    public void setFinalPath(String finalPath) {
        this.finalPath = finalPath;
    }
    
    public Long getUserId() {
        return userId;
    }
    
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    
    public void setTitle(String title) {
        this.title = title;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
    
    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }
    
    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }
    
    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }
} 